﻿#pragma once

#include <map>
#include <set>
#include <vector>
#include <memory>
#include <string>
#include <optional>

#include <cpptools/out.h>

class Permission;
class Role;
class Account;
class Token;
typedef Permission*         pms_t;
typedef Role*               role_t;
typedef std::string         string_t;
typedef std::set<role_t>    role_list_t;

namespace protect { // 受保护
    static constexpr uint8_t kNormal = 0; // 无保护
    static constexpr uint8_t kAllPms = 1; // 所有权限
    static constexpr uint8_t kNoMod = 2; // 不可修改
    static constexpr uint8_t kNoDel = 4; // 不可删除
    static constexpr uint8_t kNoDisable = 8; // 不可停用
    static constexpr uint8_t kAllRole = kAllPms; // 所有角色
    static constexpr uint8_t kSuper = kAllPms + kNoDel + kNoMod + kNoDisable; // 超级帐号
};

// 权限管理类
class Permission {
public:
    typedef std::map<uint32_t, pms_t>       list_t;
    typedef std::map<string_t, pms_t>       name_list_t;
    
    static const unsigned int kNameMaxLen = 64; // 字段最大长度
    static const unsigned int kAliasMaxLen = 32;
    static const unsigned int kDescMaxLen = 120;
    
public:
    static list_t all; // 所有权限
    static name_list_t allName;

    static bool loadData(void); // 载入数据库, 启动时调用
    static inline pms_t find(uint32_t id) { // 根据ID查找权限, nullptr未找到
        auto it = all.find(id); 
        return it != all.end() ? it->second : nullptr; 
    } 
    static inline pms_t find(const string_t& name) { // 根据名称查找权限, nullptr未找到
        auto it = allName.find(name); 
        return it != allName.end() ? it->second : nullptr;
    }

public:
    explicit Permission(uint32_t id, uint32_t sys, string_t&& name, string_t&& alias)
        : id_(id), sys_(sys), name_(std::forward<string_t>(name)), alias_(std::forward<string_t>(alias)) {
        //ct::Out::flag(pub::debug::kNode, "Permission construct, id(%u), name(%s).\n", id, name_.data());
        all.insert(std::pair<uint32_t, pms_t>(id, this)); // 数据库线程new了后需要在主线程new
        allName.insert(std::pair<string_t, pms_t>(name_, this));
    }
    ~Permission(void);

    uint32_t id(void) const { return id_; } // Get,Set
    uint32_t sys(void) const { return sys_; }
    const string_t& name(void) const { return name_; }
    void name(string_t&& s) { name_ = std::forward<string_t>(s); }
    const string_t& alias(void) const { return alias_; }
    void alias(string_t&& s) { alias_ = std::forward<string_t>(s); }

private: 
    uint32_t    id_;
    uint32_t    sys_; // 是否系统保护权限(非0是, 0否)
    string_t    name_, alias_;
};

struct PmsComp {
    bool operator()(const pms_t& left, const pms_t& right) const {
        return left->id() < right->id();
    }
};
typedef std::set<pms_t, PmsComp> pms_list_t;

// 角色类
class Role {
public:
    typedef std::map<uint32_t, role_t>      list_t;

    static const unsigned int kNameMaxLen = 32; // 字段最大长度
    static const unsigned int kDescMaxLen = 120;
    
    static list_t all; // 所有角色
    static bool loadData(void); // 载入数据库, 启动时调用
    static inline role_t find(uint32_t id) { // 根据ID查找角色节点, nullptr未找到
        auto it = all.find(id);
        return it != all.end() ? it->second : nullptr;
    }

public:
    explicit Role(uint32_t id, uint32_t sys, string_t&& name, const char* pms);
    ~Role(void);

    uint32_t id(void) const { return id_; } // Get,Set
    uint32_t sys(void) const { return sys_; }
    const string_t& name(void) const { return name_; }
    void name(string_t&& s) { name_ = std::forward<string_t>(s); }
    pms_list_t& pms(void) { return pms_; }

    inline bool pmsExist(const pms_t pmsNode) { return pms_.find(pmsNode) != pms_.end(); } // 是否有指定权限节点
    inline bool pmsExist(const string_t& name) { // 是否有指定的权限名
        auto pmsNode = Permission::find(name);
        return pmsNode ? pmsExist(pmsNode) : false;
    } 
    inline void pmsAdd(pms_t p) { pms_.insert(p); }
    inline void pmsDel(pms_t p) { pms_.erase(p); }
    inline void pmsAll(pms_list_t& all) const { // 拥有的权限列表
        for (auto& itr : pms_) {
            all.insert(itr);
        }
    }

private:
    uint32_t    id_;
    uint32_t    sys_; // 是否保护
    string_t    name_;
    pms_list_t  pms_; // 拥有权限列表
};


// 帐号类
class Account {
public:
    enum class Type : uint8_t { // 帐号类型
        JCG = 1, // 注册帐号
        UNIONID = 2, // 微信unionid
    };

    enum class TeamType : uint8_t { // 分组类型
        kPlatform = 1, // 平台分组
        kUser = 2, // 用户分组
    };


    static const unsigned int kNameMaxLen = 30; // 字段最大长度
    static const unsigned int kAliasMaxLen = 32;
    static const unsigned int kDescMaxLen = 240;
    static const unsigned int kPhoneMaxLen = 16; 
    static const unsigned int kImageMaxLen = 240;
    
    using sptr_t = std::shared_ptr<Account>;
    using wptr_t = std::weak_ptr<Account>;
    using list_t = std::map<string_t, wptr_t>; // map中存weak_ptr, 当各token下存储的节点释放则自动析构
    using team_list_t = std::vector<uint32_t>;
    using token_list_t = std::set<uint64_t>;

public:
    static list_t all; // 所有在线帐号

    static std::optional<sptr_t> find(const string_t& name); // 查找帐号

public:
    explicit Account(string_t&& name, string_t&& pwd, string_t&& alias, string_t&& image, const char* roleStr,
                    const char* pmsStr, uint8_t teamType, uint32_t team, uint32_t rate, 
                     bool repeat, uint8_t sys, uint8_t sex, uint8_t type);
    ~Account(void) { /* ct::Out::flag(pub::debug::kNode, "Account %s destory.\n", name_.c_str()); */ }

    void tokenAdd(uint64_t token) { tokens_.insert(token); } // 添加一个登陆token
    void tokenDel(uint64_t token) { tokens_.erase(token); } // 列表移除一个登陆token
    void tokenDown(uint32_t caugh, uint32_t timesec); // 下线所有登陆的token, 析构token对象并自动从关联的account中移除对token引用
    const token_list_t& tokens(void) const { return tokens_; } // token列表

    bool pmsExist(const string_t& name) const; // 是否存在指定的权限名称
    bool pmsExist(const pms_t pmsNode) const; // 是否存在指定的权限节点
    inline bool pmsExistProtect(const pms_t pmsNode) const { return (sys() & protect::kAllPms) ? true : pmsExist(pmsNode); } // 是否有指定的权限节点,有全权限保护的也判断
    inline pms_list_t& pms(void) { return pms_; } // 获取权限列表
    inline void pmsAdd(pms_t p) { pms_.insert(p); }
    inline void pmsDel(pms_t p) { pms_.erase(p); }
    void pmsAll(pms_list_t& all) const; // 拥有的权限列表

    inline role_list_t& role(void) { return role_; }
    inline void roleAdd(role_t r) { role_.insert(r); }
    inline void roleDel(role_t r) { role_.erase(r); }
    //const role_list_t& roleAll(void) const { return (sys() & protect::kAllRole) ? Role::all : role_;  } // 拥有的角色列表
    inline bool roleExistProtect(role_t r) const { return (sys() & protect::kAllRole) ? true : (role_.find(r) != role_.end()); } // 是否存在指定角色

    const string_t& name(void) const { return name_; } // Get,Set
    uint8_t sys(void) const { return (uint8_t)sys_; }
    Type type(void) const { return (Type)type_; }

    const string_t& password(void) const { return password_; }
    void password(string_t&& s) { this->password_ = std::move(s); }
    
    const string_t& alias(void) const { return alias_; }
    void alias(string_t&& s) { this->alias_ = std::move(s); }
    
    const string_t& image(void) const { return image_; }
    void image(string_t&& s) { this->image_ = std::move(s); }
    
    uint32_t team(void) const { return team_; }
    void team(uint32_t o) { this->team_ = o; }

    const team_list_t& childTeams(void) const { return this->childTeams_; }
    void addChildTeam(uint32_t team) { this->childTeams_.push_back(team); }
    
    uint32_t rate(void) const { return rate_; }
    void rate(uint32_t o) { this->rate_ = o; }
    
    bool repeat(void) const { return (bool)repeat_; }
    void repeat(uint32_t o) { this->repeat_ = o; }
    
    uint8_t sex(void) const { return (uint8_t)sex_; }
    void sex(uint8_t o) { this->sex_ = (uint8_t)o; }

    uint32_t teamType(void) const { return (uint32_t)teamType_; }
    void teamType(uint32_t t) { this->teamType_ = (uint8_t)t; }

private:
    role_list_t     role_; // 拥有的角色列表
    pms_list_t      pms_; // 拥有的权限列表
    token_list_t    tokens_; // 当前在线token列表
    team_list_t childTeams_; // 子分组列表
    string_t    name_, password_, alias_, image_;
    uint32_t    team_, rate_;
    bool        repeat_; // 重复登陆
    uint8_t     sys_; // 系统保护(0否,1所有权限,2不可被删除,4不可修改,8不可停用)
    uint8_t     sex_; // 性别(1男2女0未知)
    Type        type_; // 类型(1注册,2微信unionid)
    uint8_t     teamType_; // 分组类型(1平台, 2用户)
};


// 登陆token管理类
class Token {
public:
    typedef std::shared_ptr<Token>          sptr_t;
    typedef std::weak_ptr<Token>            wptr_t;
    typedef std::map<uint64_t, sptr_t>      list_t;

public:
    static list_t all;

    static std::optional<sptr_t> find(uint64_t); // 查找token
    static void tokenDel(uint64_t token) { all.erase(token); } // 删除指定的token

public:
    explicit Token(const Account::sptr_t& acc, uint64_t token, uint32_t timesec, uint32_t timeout, string_t&& ip)
        : acc_(acc), token_(token), uptime_(timesec), lastTime_(timesec), timeout_(timeout), ip_(std::move(ip)) {
        acc_->tokenAdd(token); // 帐号下存储此上线token值,便于后续强制下线
        //ct::Out::flag(kInfo, "Token %lu construct.\n", token_);
    }
    ~Token(void); // 析构时, 自动从帐号的在线token列表中移除

    const Account::sptr_t& accountSptr(void) const { return acc_; } // Get,Set
    uint64_t token(void) const { return token_; }
    void token(uint64_t t) { token_ = t; }
    uint32_t upTime(void) const { return uptime_; }
    void upTime(uint32_t at) { this->uptime_ = at; }
    uint32_t lastTime(void) const { return lastTime_; }
    void lastTime(uint32_t t) { this->lastTime_ = t; }
    uint32_t timeout(void) const { return timeout_; }
    const string_t& ip(void) const { return ip_; }
    void logoutCaugh(uint32_t caugh) { caugh_ = caugh; }

private:
    Account::sptr_t acc_; // 帐号节点
    uint64_t        token_;
    uint32_t        uptime_; // 上线时间
    uint32_t        lastTime_; // 最后更新时间
    uint32_t        timeout_; // 超时时间
    uint32_t        caugh_; // 下线原因
    string_t        ip_;
};